package com.tomz.xatomic.conditional;

import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.type.AnnotatedTypeMetadata;

import java.util.Iterator;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @author ZHUFEIFEI
 */
public class OnCollectionPropertyCondition extends SpringBootCondition {

        @Override
        public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
            Object propertyName = metadata.getAnnotationAttributes(ConditionalOnCollectionProperty.class.getName()).get("value");
            if (propertyName != null) {
                String keyPattern = String.format("%s%s%s", "^"
                        , propertyName.toString().replaceAll("\\.", "\\\\."), "\\[\\d+\\].*");
                Pattern pattern = Pattern.compile(keyPattern);
                /**
                 * @see org.springframework.boot.context.properties.bind.ArrayBinder
                 */
                MutablePropertySources propertySources = ((ConfigurableEnvironment)context.getEnvironment()).getPropertySources();
                Iterator<PropertySource<?>> iterator = propertySources.iterator();

                while (iterator.hasNext()) {
                    PropertySource<?> p = iterator.next();
                    if (p != null && p instanceof MapPropertySource) {
                        MapPropertySource mapProps = MapPropertySource.class.cast(p);
                        Map<String, Object> map = mapProps.getSource();
                        for (Map.Entry<String, Object> kv : map.entrySet()) {
                            if (pattern.matcher(kv.getKey()).matches()) {
                                return ConditionOutcome.match(ConditionMessage.forCondition("OnCollectionPropertyCondition").found(propertyName.toString()).atAll());
                            }
                        }
                    }
                }
            }
            return ConditionOutcome.noMatch(ConditionMessage.forCondition("OnCollectionPropertyCondition").didNotFind(propertyName.toString()).atAll());
//            return new ConditionOutcome(false, "property not found : " + propertyName);
        }
    }